package com.pai4j.ugc.service;

import com.pai4j.common.bean.PAIPageResponseBeanUtil;
import com.pai4j.common.enums.InteractionMessageTypeEnum;
import com.pai4j.common.enums.MessageTypeEnum;
import com.pai4j.domain.vo.request.interaction.InteractionMessageQueryRequestVO;
import com.pai4j.domain.vo.request.interaction.MarkInteractionMessageReadRequestVO;
import com.pai4j.domain.vo.request.interaction.SystemMessageSendRequestVO;
import com.pai4j.domain.vo.response.UserBaseResponseInfoVO;
import com.pai4j.domain.vo.response.interaction.InteractionMessagePageResponseVO;
import com.pai4j.domain.vo.response.interaction.InteractionMessageResponseVO;
import com.pai4j.domain.vo.response.interaction.InteractionMessageStatisticsVO;
import com.pai4j.domain.vo.response.interaction.SystemMessageSendResponseVO;
import com.pai4j.ugc.repository.dao.IInteractionMessageDAO;
import com.pai4j.ugc.repository.entity.InteractionMessageEntity;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 互动消息服务
 * 负责互动消息的业务逻辑处理，包括查询、未读管理、统计等
 * 
 * 设计原则：
 * 1. 查询互动消息列表时，不自动标记已读（与聊天消息不同）
 * 2. 用户需要主动调用标记已读接口
 * 3. 支持批量操作和灵活的查询条件
 * 4. 高扩展性，支持按类型、时间等多维度查询
 * 
 * @author PAI4J Team
 */
@Slf4j
@Service
public class InteractionMessageService {
    
    @Autowired
    private IInteractionMessageDAO interactionMessageDAO;
    
    @Autowired
    private AccountService accountService;
    
    /**
     * 分页查询互动消息列表
     * 注意：此方法不会自动标记消息为已读，需要用户主动调用标记已读接口
     * 
     * @param request 查询请求
     * @return 分页结果
     */
    public InteractionMessagePageResponseVO pageInteractionMessages(InteractionMessageQueryRequestVO request) {
        log.info("分页查询互动消息，receiver: {}, type: {}, unreadOnly: {}, pageNo: {}, pageSize: {}", 
                request.getReceiver(), request.getType(), request.getUnreadOnly(), 
                request.getPageNo(), request.getPageSize());
        
        // 构建分页参数
        Pageable pageable = PageRequest.of(
                request.getPageNo() - 1, 
                request.getPageSize()
        );
        
        Page<InteractionMessageEntity> page;
        
        // 根据查询条件选择不同的查询方法
        if (request.getRecentDays() != null && request.getRecentDays() > 0) {
            // 查询最近N天的消息
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.DAY_OF_MONTH, -request.getRecentDays());
            Date afterDate = calendar.getTime();
            
            page = interactionMessageDAO.findByReceiverAfterDate(
                    request.getReceiver(), 
                    afterDate, 
                    request.getUnreadOnly() != null && request.getUnreadOnly(),
                    pageable
            );
        } else if (request.getType() != null) {
            // 按互动消息类型查询（使用messageType字段）
            page = interactionMessageDAO.findByReceiverAndMessageTypeOrderBySendDateDesc(
                    request.getReceiver(), 
                    request.getType(), 
                    pageable
            );
        } else if (request.getUnreadOnly() != null && request.getUnreadOnly()) {
            // 只查询未读消息
            page = interactionMessageDAO.findUnreadByReceiverOrderBySendDateDesc(
                    request.getReceiver(), 
                    pageable
            );
        } else {
            // 查询全部消息
            page = interactionMessageDAO.findByReceiverOrderBySendDateDesc(
                    request.getReceiver(), 
                    pageable
            );
        }
        
        // 转换为响应VO
        List<InteractionMessageResponseVO> messageList = convertToResponseVOList(page.getContent());
        
        // 构建分页响应
        InteractionMessagePageResponseVO response = new InteractionMessagePageResponseVO();
        response.setMessages(messageList);
        response.setPageNo(request.getPageNo());
        response.setPageSize(request.getPageSize());
        response.setTotalCount(page.getTotalElements());
        response.setTotalPages(page.getTotalPages());
        response.setHasNext(page.hasNext());
        
        log.info("查询完成，返回 {} 条消息，总数：{}", messageList.size(), page.getTotalElements());
        return response;
    }
    
    /**
     * 查询未读互动消息数量
     * 
     * @param receiver 接收者账号
     * @return 未读消息数量
     */
    public long getUnreadCount(String receiver) {
        long count = interactionMessageDAO.countUnreadByReceiver(receiver);
        log.debug("查询未读互动消息数，receiver: {}, count: {}", receiver, count);
        return count;
    }
    
    /**
     * 查询指定类型的未读互动消息数量
     * 
     * @param receiver 接收者账号
     * @param type 消息类型
     * @return 未读消息数量
     */
    public long getUnreadCountByType(String receiver, Integer type) {
        long count = interactionMessageDAO.countUnreadByReceiverAndMessageType(receiver, type);
        log.debug("查询指定类型未读互动消息数，receiver: {}, type: {}, count: {}", receiver, type, count);
        return count;
    }
    
    /**
     * 获取互动消息统计信息
     * 
     * @param receiver 接收者账号
     * @return 统计信息
     */
    public InteractionMessageStatisticsVO getStatistics(String receiver) {
        log.info("获取互动消息统计信息，receiver: {}", receiver);
        
        InteractionMessageStatisticsVO statistics = new InteractionMessageStatisticsVO();
        
        // 总未读消息数
        statistics.setTotalUnreadCount(interactionMessageDAO.countUnreadByReceiver(receiver));
        
        // 计算今天、本周、本月的消息数
        Calendar calendar = Calendar.getInstance();
        
        // 今天
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date todayStart = calendar.getTime();
        Pageable todayPageable = PageRequest.of(0, 1);
        Page<InteractionMessageEntity> todayPage = interactionMessageDAO.findByReceiverAfterDate(
                receiver, todayStart, false, todayPageable);
        statistics.setTodayCount(todayPage.getTotalElements());
        
        // 本周
        calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        Date weekStart = calendar.getTime();
        Page<InteractionMessageEntity> weekPage = interactionMessageDAO.findByReceiverAfterDate(
                receiver, weekStart, false, todayPageable);
        statistics.setWeekCount(weekPage.getTotalElements());
        
        // 本月
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        Date monthStart = calendar.getTime();
        Page<InteractionMessageEntity> monthPage = interactionMessageDAO.findByReceiverAfterDate(
                receiver, monthStart, false, todayPageable);
        statistics.setMonthCount(monthPage.getTotalElements());
        
        log.info("统计信息：totalUnread: {}, today: {}, week: {}, month: {}", 
                statistics.getTotalUnreadCount(), statistics.getTodayCount(), 
                statistics.getWeekCount(), statistics.getMonthCount());
        
        return statistics;
    }
    
    /**
     * 批量标记互动消息为已读
     * 
     * @param request 标记已读请求
     * @return 标记已读的消息数量
     */
    @Transactional(rollbackFor = Exception.class)
    public int markMessagesAsRead(MarkInteractionMessageReadRequestVO request) {
        log.info("标记互动消息为已读，receiver: {}, markAll: {}, messageIds: {}", 
                request.getReceiver(), request.getMarkAll(), request.getMessageIds());
        
        int updatedCount;
        
        if (request.getMarkAll() != null && request.getMarkAll()) {
            // 标记所有未读消息为已读
            updatedCount = interactionMessageDAO.markAllMessagesAsReadByReceiver(request.getReceiver());
            log.info("标记所有未读消息为已读，更新数量：{}", updatedCount);
        } else if (CollectionUtils.isNotEmpty(request.getMessageIds())) {
            // 批量标记指定消息为已读
            updatedCount = interactionMessageDAO.markMessagesAsReadByIds(
                    request.getMessageIds(), 
                    request.getReceiver()
            );
            log.info("批量标记消息为已读，更新数量：{}", updatedCount);
        } else {
            log.warn("无效的标记已读请求，既没有指定messageIds也没有设置markAll");
            return 0;
        }
        
        return updatedCount;
    }
    
    /**
     * 一键全部已读
     * 标记指定用户的所有未读互动消息为已读
     * 
     * @param receiver 接收者账号
     * @param messageType 消息类型（可选，不传则标记所有类型）
     * @return 标记已读的消息数量
     */
    @Transactional(rollbackFor = Exception.class)
    public int markAllAsRead(String receiver, Integer messageType) {
        log.info("一键全部已读，receiver: {}, messageType: {}", receiver, messageType);
        
        if (StringUtils.isBlank(receiver)) {
            log.warn("receiver为空，无法执行一键全部已读");
            return 0;
        }
        
        int updatedCount;
        
        if (messageType != null) {
            // 标记指定互动消息类型的所有未读消息为已读（messageType）
            updatedCount = interactionMessageDAO.markAllMessagesAsReadByReceiverAndType(receiver, messageType);
            log.info("标记指定类型的所有未读消息为已读，messageType: {}, 更新数量: {}", messageType, updatedCount);
        } else {
            // 标记所有未读消息为已读
            updatedCount = interactionMessageDAO.markAllMessagesAsReadByReceiver(receiver);
            log.info("标记所有未读消息为已读，更新数量: {}", updatedCount);
        }
        
        return updatedCount;
    }
    
    /**
     * 转换互动消息实体列表为响应VO列表
     * 
     * @param entities 实体列表
     * @return 响应VO列表
     */
    private List<InteractionMessageResponseVO> convertToResponseVOList(List<InteractionMessageEntity> entities) {
        if (CollectionUtils.isEmpty(entities)) {
            return Collections.emptyList();
        }
        
        // 批量查询用户信息
        Set<String> userIds = new HashSet<>();
        entities.forEach(entity -> {
            userIds.add(entity.getSender());
            userIds.add(entity.getReceiver());
        });
        
        Map<String, UserBaseResponseInfoVO> userMap = accountService.batchGet(userIds);
        
        // 转换为响应VO
        return entities.stream().map(entity -> {
            InteractionMessageResponseVO vo = new InteractionMessageResponseVO();
            BeanUtils.copyProperties(entity, vo);
            
            vo.setId(entity.getId());
            vo.setSenderId(entity.getSender());
            vo.setReceiverId(entity.getReceiver());
            vo.setSendTime(entity.getSendDate() != null ? entity.getSendDate().getTime() : null);
            
            // 设置互动消息类型和类型名称
            vo.setMessageType(entity.getMessageType());
            if (entity.getMessageType() != null) {
                InteractionMessageTypeEnum typeEnum = InteractionMessageTypeEnum.fromCode(entity.getMessageType());
                vo.setMessageTypeName(typeEnum.getName());
            }
            
            // 设置用户信息
            vo.setSender(userMap.get(entity.getSender()));
            vo.setReceiver(userMap.get(entity.getReceiver()));
            
            return vo;
        }).collect(Collectors.toList());
    }
    
    /**
     * 查询互动消息详情
     * 
     * @param messageId 消息ID
     * @return 消息详情
     */
    public InteractionMessageResponseVO getMessageDetail(Long messageId) {
        log.debug("查询互动消息详情，messageId: {}", messageId);
        
        Optional<InteractionMessageEntity> optional = interactionMessageDAO.findById(messageId);
        if (!optional.isPresent()) {
            log.warn("互动消息不存在，messageId: {}", messageId);
            return null;
        }
        
        InteractionMessageEntity entity = optional.get();
        List<InteractionMessageResponseVO> voList = convertToResponseVOList(Collections.singletonList(entity));
        
        return CollectionUtils.isNotEmpty(voList) ? voList.get(0) : null;
    }
    
    /**
     * 发送系统消息
     * 系统消息是一种特殊的互动消息，用于平台公告、活动通知、系统维护通知等场景
     * 支持群发（全部用户或指定用户列表）
     * 
     * @param request 系统消息发送请求
     * @return 发送结果
     */
    @Transactional(rollbackFor = Exception.class)
    public SystemMessageSendResponseVO sendSystemMessage(SystemMessageSendRequestVO request) {
        log.info("【系统消息】开始发送，标题: {}, 接收者类型: {}", request.getTitle(), request.getReceiverType());
        
        SystemMessageSendResponseVO response = new SystemMessageSendResponseVO();
        int successCount = 0;
        int failCount = 0;
        
        // 生成批次ID
        String batchId = "SYS_MSG_" + System.currentTimeMillis();
        
        try {
            // 参数校验
            if (StringUtils.isBlank(request.getContent())) {
                response.setSuccessCount(0);
                response.setFailCount(0);
                response.setMessage("消息内容不能为空");
                return response;
            }
            
            // 获取接收者列表
            List<String> receivers = getReceivers(request);
            if (CollectionUtils.isEmpty(receivers)) {
                response.setSuccessCount(0);
                response.setFailCount(0);
                response.setMessage("接收者列表为空");
                return response;
            }
            
            log.info("【系统消息】接收者数量: {}", receivers.size());
            
            // 批量创建系统消息
            Date now = new Date();
            for (String receiver : receivers) {
                try {
                    InteractionMessageEntity message = new InteractionMessageEntity();
                    message.setSender("system"); // 系统消息发送者为"system"
                    message.setReceiver(receiver);
                    message.setMessage(buildSystemMessageContent(request));
                    message.setContent(request.getContent());
                    message.setImage(request.getImage());
                    message.setType(MessageTypeEnum.SYSTEM.getType());
                    message.setIsRead(false);
                    message.setSendDate(now);
                    
                    // 设置资源跳转链接
                    if (StringUtils.isNotBlank(request.getJumpUrl())) {
                        message.setResourceUrl(request.getJumpUrl());
                    }
                    
                    // 设置扩展数据（包含分类、标题等）
                    Map<String, String> extMap = new HashMap<>();
                    if (StringUtils.isNotBlank(request.getTitle())) {
                        extMap.put("title", request.getTitle());
                    }
                    if (StringUtils.isNotBlank(request.getCategory())) {
                        extMap.put("category", request.getCategory());
                    }
                    extMap.put("batchId", batchId);
                    if (StringUtils.isNotBlank(request.getExtData())) {
                        extMap.put("customExtData", request.getExtData());
                    }
                    // TODO: 使用JsonUtil序列化extMap
                    // message.setExtData(JsonUtil.toJsonString(extMap));
                    
                    // 生成消息UUID（用于幂等性控制）
                    String messageUuid = generateSystemMessageUuid(receiver, batchId, now.getTime());
                    message.setMessageUuid(messageUuid);
                    
                    // 检查是否已存在（幂等性）
                    if (!interactionMessageDAO.existsByMessageUuid(messageUuid)) {
                        interactionMessageDAO.save(message);
                        successCount++;
                    } else {
                        log.warn("【系统消息】消息已存在，跳过发送，receiver: {}, messageUuid: {}", receiver, messageUuid);
                        successCount++; // 幂等性场景也算成功
                    }
                } catch (Exception e) {
                    log.error("【系统消息】发送失败，receiver: {}", receiver, e);
                    failCount++;
                }
            }
            
            response.setSuccessCount(successCount);
            response.setFailCount(failCount);
            response.setBatchId(batchId);
            response.setMessage(String.format("发送完成，成功: %d，失败: %d", successCount, failCount));
            
            log.info("【系统消息】发送完成，batchId: {}, 成功: {}, 失败: {}", batchId, successCount, failCount);
            
        } catch (Exception e) {
            log.error("【系统消息】发送异常", e);
            response.setSuccessCount(successCount);
            response.setFailCount(failCount);
            response.setBatchId(batchId);
            response.setMessage("发送异常: " + e.getMessage());
        }
        
        return response;
    }
    
    /**
     * 获取接收者列表
     * 
     * @param request 系统消息发送请求
     * @return 接收者账号列表
     */
    private List<String> getReceivers(SystemMessageSendRequestVO request) {
        if (request.getReceiverType() == SystemMessageSendRequestVO.ReceiverType.SPECIFIC) {
            // 指定用户列表
            return request.getReceivers();
        } else if (request.getReceiverType() == SystemMessageSendRequestVO.ReceiverType.ALL) {
            // 全部用户 - 需要从用户服务获取所有活跃用户列表
            // TODO: 调用用户服务获取所有活跃用户
            // return userService.getAllActiveUsers();
            log.warn("【系统消息】暂不支持全部用户群发，请使用指定用户列表");
            return Collections.emptyList();
        }
        return Collections.emptyList();
    }
    
    /**
     * 构建系统消息内容
     * 
     * @param request 系统消息发送请求
     * @return 消息内容
     */
    private String buildSystemMessageContent(SystemMessageSendRequestVO request) {
        if (StringUtils.isNotBlank(request.getTitle())) {
            return "【" + request.getTitle() + "】" + request.getContent();
        }
        return request.getContent();
    }
    
    /**
     * 生成系统消息UUID（用于幂等性控制）
     * 
     * @param receiver 接收者
     * @param batchId 批次ID
     * @param timestamp 时间戳
     * @return 消息UUID
     */
    private String generateSystemMessageUuid(String receiver, String batchId, long timestamp) {
        return String.format("system:%s:%d:%s:%d", 
                receiver, 
                MessageTypeEnum.SYSTEM.getType(), 
                batchId, 
                timestamp);
    }
}
